//===========================通用动态资源文件加载器==========
;(function(){
    /**
     * 插件模块包
     * @type {{}}
     */
    var modules = {};
    /**
     * 本地语言包
     * @type {{}}
     */
    var locales = {};
    /**
     * @ignore
     * @type {{}}
     */
    var queues = {};

    /***
     * 加载单独Js文件
     * @param url {string}
     * @param callback {*|function}
     */
    function loadJs(url, callback) {
        var done = false;
        var script = document.createElement('script');//创建script dom
        script.type = 'text/javascript';
        script.language = 'javascript';
        script.src = url;
        script.onload = script.onreadystatechange = function () {
            if (!done && (!script.readyState || script.readyState == 'loaded' || script.readyState == 'complete')) {
                done = true;
                script.onload = script.onreadystatechange = null;
                if (callback) {
                    callback.call(script);
                }
            }
        }
        document.getElementsByTagName("head")[0].appendChild(script);
    };// loadJs end
    /**
     * 先loadJs，加载完成remove,再callback
     * @param url {string}
     * @param callback {*|function}
     */
    function runJs(url, callback) {
        loadJs(url, function () {
            document.getElementsByTagName("head")[0].removeChild(this);
            if (callback) {
                callback();
            }
        });
    };// runJs end
    /***
     * 单独加载css文件
     * @param url {string}
     * @param callback {*|function}
     */
    function loadCss(url, callback) {
        var link = document.createElement('link');
        link.rel = 'stylesheet';
        link.type = 'text/css';
        link.media = 'screen';
        link.href = url;
        document.getElementsByTagName('head')[0].appendChild(link);
        if (callback) {
            callback.call(link);
        }
    };// loadCss end
    /**
     * 加载单独模块
     * @param name {string}
     * @param callback (*|function)
     */
    function loadSingle(name, callback) {//加载单一plugin
        queues[name] = 'loading';//把整个plugin的状态设置为loading
        var module = modules[name];
        var jsStatus = 'loading';//把js状态设置为loading
        var cssStatus = (module['css']) ? 'loading' : 'loaded';
        if (module['css']) {//加载css
            var url = module['css'];
            loadCss(url, function () {
                cssStatus = 'loaded';
                if (jsStatus == 'loaded' && cssStatus == 'loaded') {
                    finish();
                }
            });//loadCss end
        }
        url = module['js'];
        loadJs(url, function () {
            jsStatus = 'loaded';
            if (jsStatus == 'loaded' && cssStatus == 'loaded') {
                finish();
            }
        });//loadJs end
        function finish() {
            queues[name] = 'loaded';
            bs.using.onProgress(name);
            if (callback) {
                callback();
            }
        }
    };//loadSingle end
    /***
     * 加载模块资源文件，如果有dependencies属性，则先加载dependencies，递归加载dependencies
     * @param name {string}
     * @param callback {*|function}
     */
    function loadModule(name, callback) {//加载主模块
        var mm = [];
        var doLoad = false;
        if (typeof name == 'string') {
            add(name);
        } else {
            for (var i = 0; i < name.length; i++) {
                add(name[i]);
            }
        }
        function add(name) {
            if (!modules[name]) return;//如果modules中没有这个plugin那退出
            var d = modules[name]['dependencies'];  //如果有，查看它是否依赖其他plugin
            if (d) { //如果依赖，就加载依赖的plugin.同时在加载依赖的plugin的依赖。注意循环中调用了add,是递归
                for (var i = 0; i < d.length; i++) {
                    add(d[i]);
                }
            }
            mm.push(name);
        };//add end
        function finish() {
            if (callback) {
                callback();
            }
            bs.using.onLoad(name);//调用onLoad，传递name 为参数
        };//finish end
        var time = 0;//超时用
        function loadMm() {
            if (mm.length) {
                var m = mm[0];  // the first module
                if (!queues[m]) {//状态序列中没有这个plugin的信息，说明没有加载这个plug,调用laodSingle进行加载
                    doLoad = true;
                    loadSingle(m, function () {
                        mm.shift();//加载完成后，将这个元素从数组去除，在继续加载，直到数组
                        loadMm();
                    });
                } else if (queues[m] == 'loaded') {//如果这个plugin已经加载，就不用加载，以为mm中可能有重复项
                    mm.shift();
                    loadMm();
                } else {
                    if (time < bs.using.timeout) {//超时时候，10秒钟调用一次loadMn().注意arguments.callee代表函数本身
                        time += 10;
                        setTimeout(arguments.callee, 10);
                    }
                }
            } else {
                if (bs.using.locale && doLoad == true && locales[bs.using.locale]) {
                    var url = locales[bs.using.locale];
                    runJs(url, function () {
                        finish();
                    });
                } else {
                    finish();
                }
            }
        };//loadMm end
        loadMm();
    };//loadModule end
    /**
     * @class 资源加载功能
     * @description  资源加载功能
     * @type {{modules: {}, locales: {}, base: string, locale: null, timeout: number, load: load, onProgress: onProgress, onLoad: onLoad}}
     */
    bs.using = {
        /**
         * 模块包
         * @public
         * @field
         */
        modules:modules,
        /**
         * 语言包
         * @public
         * @field
         */
        locales:locales,
        /**
         * 插件根目录
         * @public
         * @field
         */
        base:bs.usingDir + 'plugins/',
        /**
         * 当使用使用的语言
         * @public
         * @field
         */
        locale:null,
        /***
         * 加载超时
         * @ignore
         */
        timeout: 2000,//加载超时事件
        /***
         * 加载资源(module|css|js)文件
         * @function
         * @param name
         * @param callback
         */
        load: function (name, callback) {
            if (/\.css$/i.test(name)) {
                loadCss(name, callback);
            }else if(/\.js$/i.test(name)){
                loadJs(name, callback);
            }else{
                loadModule(name, callback);//如果直接传递一个插件名，就去modole数组中加载
            }
        },//load end
        /**
         * 当一个模块加载完会触发此函数
         * @ignore
         * @function
         * @param name
         */
        onProgress: function (name) {
        },
        /**
         * 当一个模块和其依赖都加载完会触发此函数
         * @ignore
         * @function
          * @param name
         */
        onLoad: function (name) {
        }
    };
    
})();